package com.rabbitmq.confirm;

import com.rabbitmq.client.*;
import com.rabbitmq.utils.RabbitMQUtils;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Receive01 {
    public static void main(String[] args) {
        //创建工厂对象用于指定链接的信息
        //创建链接以及通道,并添加异常处理同时在try..catch执行完成后自动释放资源
        try {
            Connection connection = RabbitMQUtils.getConnection();
            Channel channel = connection.createChannel();

            String queueName = "confirmQueue";
            channel.queueDeclare(queueName, true, false, false, null);

            String exchangeName = "directExchange";
            channel.exchangeDeclare(exchangeName, "direct", true);

            channel.queueBind(queueName, exchangeName, "confirmKey");
            /**
             * basicConsume 方法参数 2为消息是否自动确认
             * true表示自动确认 : 消息接收成功后无论是否完成处理消息都会出队(从队列中移除)可能会造成丢失消息
             * false表示手动确认: 消息处理完成后必须手动确认消息否则消息不会从队列中移除这可能会造成消息的重复处理
             */
            channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
                /**
                 * 消息处理的方法
                 */
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                           byte[] body) throws IOException {
                    Channel c = this.getChannel();
                    try {
//                        System.out.println(10 / 0);
                        //获取消息
                        String message = new String(body);
                        //处理消息,消息处理有很多种方法例如写入数据库等等
                        System.out.println("Receive01:\t" + message);
                        //获取消息编号
                        long messageTag = envelope.getDeliveryTag();
                        /**
                         * 手动确认消息,确认后将消息从队列中移除
                         * 参数 1 为消息编号
                         * 参数 2 为是否批量确认,true表示批量,要确认所有消息等于当前消息编号的所有消息
                         */
                        c.basicAck(messageTag, true);
                    } catch (Exception e) {
                        System.out.println(e.getClass());
                        //出现异常表示消息可能处理成功或处理失败,将消息放回到队列的尾巴再次尝试处理消息
                        c.basicRecover();
                    }
                }
            });
            System.out.println("消息接收成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
